#include <boost/property_tree/json_parser.hpp>
#include <exception>
#include <iostream>
#include "json_message_processor.h"
#include "utility.hpp"
#include "message_types_res.h"
#include "loghelper.h"
#include "app_common.h"

using namespace boost;
using namespace boost::property_tree;
using namespace std;
using namespace RockLog;
using namespace Utility;

JsonMessageProcessor::JsonMessageProcessor()
{
}

JsonMessageProcessor::~JsonMessageProcessor()
{
}

bool JsonMessageProcessor::decodeHeartbeatReq(const std::string &json, HeartbeatReq_t &req)
{
    try
    {
        stringstream ss;
        ss << json;
        read_json(ss, _pt);

        auto data = _pt.get_child_optional("data");
        if (data)
        {
            auto a = data->get_optional<std::string>("ip");
            if (a)
                req.ip = *a;

            auto b = data->get_optional<std::string>("mac");
            if (b)
                req.mac = *b;
            return true;
        }

        return true;
    }
    catch (std::exception &e)
    {
        LOG(kErr) << "!!! decodeHeartbeatReq: unknow error: " << e.what() << endl;
    }
    return false;
}

bool JsonMessageProcessor::decodeHeartbeatRsp(const std::string &json, HeartbeatRsp_t &rsp)
{
    try
    {
        stringstream ss;
        ss << json;
        read_json(ss, _pt);

        auto data = _pt.get_child_optional("data");
        if (data)
        {
            auto a = data->get_optional<int>("code");
            if (a)
                rsp.code = *a;

            auto b = data->get_optional<std::string>("message");
            if (b)
                rsp.message = *b;
            return true;
        }

        return true;
    }
    catch (std::exception &e)
    {
        LOG(kErr) << "!!! decodeHeartbeatRsp: unknow error: " << e.what() << endl;
    }
    return false;
}

bool JsonMessageProcessor::decodeLoginReq(const std::string &json, LoginReq_t &req)
{
    try
    {
        stringstream ss;
        ss << json;
        read_json(ss, _pt);

        auto data = _pt.get_child_optional("data");
        if (data)
        {
            auto a = data->get_optional<std::string>("session_id");
            if (a)
                req.sessionId = *a;
        }

        return true;
    }
    catch (std::exception &e)
    {
        LOG(kErr) << "!!! decodeLoginReq: unknow error: " << e.what() << endl;
    }
    return false;
}

bool JsonMessageProcessor::decodeLogoutReq(const std::string &json, LogoutReq_t &req)
{
    try
    {
        stringstream ss;
        ss << json;
        read_json(ss, _pt);

        auto data = _pt.get_child_optional("data");
        if (data)
        {
            auto a = data->get_optional<std::string>("session_id");
            if (a)
                req.sessionId = *a;

            return true;
        }
    }
    catch (std::exception &e)
    {
        LOG(kErr) << "!!! decodeLogoutReq: unknow error: " << e.what() << endl;
    }

    return false;
}

bool JsonMessageProcessor::decodeLogoutRsp(const std::string &json, LogoutRsp_t &req)
{
    try
    {
        stringstream ss;
        ss << json;
        read_json(ss, _pt);

        auto data = _pt.get_child_optional("data");
        if (data)
        {
            auto a = data->get_optional<int>("code");
            if (a)
                req.code = *a;

            return true;
        }
    }
    catch (std::exception &e)
    {
        LOG(kErr) << "!!! decodeLogoutRsp: unknow error: " << e.what() << endl;
    }

    return false;
}

bool JsonMessageProcessor::decodeLoginRsp(const std::string &json, LoginRsp_t &rsp)
{
    try
    {
        stringstream ss;
        ss << json;
        read_json(ss, _pt);

        auto data = _pt.get_child_optional("data");
        if (data)
        {
            auto a = data->get_optional<int>("code");
            if (a)
                rsp.code = *a;

            return true;
        }

        return true;
    }
    catch (std::exception &e)
    {
        LOG(kErr) << "!!! decodeLoginRsp: unknow error: " << e.what() << endl;
    }
    return false;
}

//////////////////////////////////////////////////////////////////////

std::string JsonMessageProcessor::encodeHeartbeatReq(const HeartbeatReq_t &req)
{
    ptree pt, data;

    pt.put("timestamp", getTimeStamp());
    data.put("ip", req.ip);
    data.put("mac", req.mac);

    pt.add_child("data", data);

    ostringstream ss;
    write_json(ss, pt);
    return ss.str();
}

std::string JsonMessageProcessor::encodeHeartbeatRsp(const HeartbeatRsp_t &rsp)
{
    ptree pt, data;

    pt.put("timestamp", getTimeStamp());
    data.put("code", to_string(rsp.code));
    data.put("message", rsp.message);

    pt.add_child("data", data);

    ostringstream ss;
    write_json(ss, pt);
    return ss.str();
}

std::string JsonMessageProcessor::encodeLoginReq(const LoginReq_t &req)
{
    ptree pt, data;

    pt.put("timestamp", getTimeStamp());
    data.put("session_id", req.sessionId);
    pt.add_child("data", data);

    ostringstream ss;
    write_json(ss, pt);
    return ss.str();
}

std::string JsonMessageProcessor::encodeLoginRsp(const LoginRsp_t &rsp)
{
    ptree pt, data;

    pt.put("timestamp", getTimeStamp());
    data.put("code", to_string(rsp.code));
    data.put("message", rsp.message);

    pt.add_child("data", data);

    ostringstream ss;
    write_json(ss, pt);
    return ss.str();
}

std::string JsonMessageProcessor::encodeLogoutReq(const LogoutReq_t &req)
{
    ptree pt, data;

    pt.put("timestamp", getTimeStamp());
    data.put("session_id", req.sessionId);

    pt.add_child("data", data);

    ostringstream ss;
    write_json(ss, pt);
    return ss.str();
}

std::string JsonMessageProcessor::encodeLogoutRsp(const LogoutRsp_t &rsp)
{
    ptree pt, data;

    pt.put("timestamp", getTimeStamp());
    data.put("code", to_string(rsp.code));
    data.put("message", rsp.message);

    pt.add_child("data", data);

    ostringstream ss;
    write_json(ss, pt);
    return ss.str();
}
